<!DOCTYPE html>
<html>
<head>
<title></title>
<script type="text/javascript" src="lib/jsbn.js"></script>
<script type="text/javascript" src="lib/prng4.js"></script>
<script type="text/javascript" src="lib/rng.js"></script>
<script type="text/javascript" src="lib/base64.js"></script>
<script type="text/javascript" src="lib/rsa.js"></script>
</head>
<body>

<script type="text/javascript">

// var rsa_m = 'aa6efa10ca436173d9af82df8be8c6cc19a4564aef654b6cb0d6f8a90dafe7e0b29dd1642efa958e1c93f1afa594e43d190b5d2acdab18d794ca794c28cb93e163132d0c41da05566391f54c8508eef5b2094cb79fab53d1bbb9d501dda88c03ebfdd2453b5c9345592bc3cd90e0702fc191cc23e4833ceb75755216c414e021';
// var rsa_e = '10001'
// var rsa = new RSAKey();
// rsa.setPublic(rsa_m, rsa_e);
// var r = rsa.encrypt("abc");

// console.log(r);

var MOD = 4294967296 - 1;
var MOD2 = MOD * MOD;

var BigIntMethods = {
	isBigInt: true,
	clean: function(){
		if(this.isZero()){
			this.pop();
		}
	},
	isZero: function(){
		if(!this[1]) return 0;
		if(this[0]) return false;
		if(!this[2]) return true;
		return this[2].isZero();
	},
	isNegative: function(){
		return this[1] < 0;
	},
	toNumber: function(){
		var a = [this[0]];
		if(this[2]){
			a = this[2].toNumber().concat(a);
		}
		return a;
	},
	clone: function(){
		var n = BigInt(0);
		n[0] = this[0];
		n[1] = this[1];
		if(this[2]){
			n[2] = this[2].clone();
		}
		return n;
	},
	abs: function(){
		this[1] = 1;
		return this;
	},
	add: function(n){
		if(!n) return this;
		if(typeof(n) == 'number'){
			if(isNaN(n)) return this;
			if(n < MOD){
				this[0] += n;
				if(this[0] < MOD){
					return this;
				} else {
					this[0] -= MOD;
					if(!this[2]){
						this[2] = BigInt(1);
					} else {
						this[2].add(1);
					}
					return this;
				}
			} else if(n === MOD){
				if(this[2]){
					this[2].add(1);
				} else {
					this[2] = BigInt(1);
				}
				return this;
			} else {
				return this.add(BigInt(n));
			}
		} else if(n.isBigInt){
			
			if(!n[1]) return this;

			if(n === this){
				n = this.clone();
			}
			if(n[2]){
				if(this[2]){
					this[2].add(n[2]);
				} else {
					this[2] = n[2].clone();
				}
			}
			this[0] += n[0];
			if(this[0] > MOD){
				this[0] -= MOD;
				if(this[2]){
					this[2].add(1);
				} else {
					this[2] = BigInt(1);
				}
			}
			n = null;
		}
		return this;
	},
	sub: function(n){
		if(!n) return this;
		if(typeof(n) == 'number'){
			if(isNaN(n)) return this;
			if(n < MOD){
				this[0] -= n;
				if(this[0] >= 0){
					return this;
				} else {
					this[0] = -this[0];
					this[1] = -1;
					return this;
				}
			} else if(n === MOD){
				if(this[2]){
					this[2].sub(1);
				} else {
					this[2] = BigInt(1);
					this[1] = -1;
				}
				return this;
			} else {
				return this.add(BigInt(n));
			}
			return this.sub(BigInt(n));
		} else if(n.isBigInt){
			if(!n[1]) return this;
			if(n === this){
				n = this.clone();
			}
			if(n[2]){
				if(this[2]){
					this[2].sub(n[2]);
				} else {
					this[2] = n[2].clone();
				}
			}

			this[0] -= n[0];
			if(this[0] < 0){
				this[0] += MOD;
				if(!this[2]){
					this[1] = -1;
					this[2] = BigInt(1);
				} else {
					this[2].add(1);
				}
			}
			// this.clean();
			n = null;
		}
		return this;
	}
};

function backShorter(a, b, f){
	var sub = Math.abs(a.length - b.length);
	if(a.length > b.length){
		for(var i = sub; i < a.length; i++){
			f(a, i, b, i - sub);
		}
	} else {
		for(var i = 0; i < a.length; i++){
			f(a, i, b, i + sub);
		}
	}
}
function forwardLonger(a, b, f){
	var len = Math.max(a.length, b.length);
	for(var i = 0; i < len; i++){
		f(a, b, i);
	}
}
function climb(arg, a, b, f){
	arg.a = a = f(a, b, arg.add);
	if(arg.a >= MOD){
		arg.a = arg.a % MOD;
		arg.add = (a / MOD) << 0;
	} else {
		arg.add = 0;
	}
	return arg.a;
}
function trimArray(arr){
	while(arr.length){
		if(arr[arr.length - 1] > 0) break;
		arr.pop();
	}
}

var UBigIntegerMethods = {
	isZero: function(){
		return this.T.length < 1;
	},
	each: function(f){
		this.T.forEach(f.bind(this));
	},
	backEach: function(f){
		var i = this.T.length;
		while(--i >= 0){
			f(this.T[i], i, this.T);
		}
	},
	equal: function(n){
		if(this.T.length != n.T.length) return false;
		for(var i = n.T.length - 1; i >= 0; i--){
			if(n.T[i] != this.T[i]) return false;
		}
		return true;
	},
	lessThan: function(n){
		if(n.isZero()) return n.isZero();
		if(n.T.length == this.T.length){
			for(var i = n.T.length - 1; i >= 0; i--){
				if(n.T[i] === this.T[i]) continue;
				return this.T[i] < n.T[i];
			}
			return true;
		} else {
			return this.T.length < n.T.length;
		}
	},
	zero: function(){
		this.T.splice(0, this.T.length);
		return this;
	},
	clone: function(copy){
		var i = UBigInteger(0);
		i.T = !copy ? this.T : this.T.slice(0);
		return i;
	},
	trim: function(){
		trimArray(this.T);
		return this;
	},
	_add: function(arg, output, input, offset, climbMethod){
		var I;
		offset = offset || 0;
		forwardLonger(output, input, function(a, b, i){
			I = i + offset;
			a[I] = climb(arg, a[I], b[i], climbMethod);
		});
		if(arg.add) output.push(arg.add);
	},
	_ADD: function(arr, offset){
		var arg = {};
		this._add(arg, this.T, arr, offset, function(a, b, add){
			return (a || 0) + (b || 0) + (add || 0);
		});
		return this;
	},
	add: function(n, offset){
		if(n.isZero() || !n) return this;
		return this._ADD(n.T, offset);
	},
	sub: function(n){

		if(n.isZero() || !n) return this;

		if(this.lessThan(n)) return this.zero();

		var add = 0;
		forwardLonger(this.T, n.T, function(a, b, i){
			a[i] = (a[i] || 0) - (b[i] || 0) + add;
			if(a[i] < 0){
				a[i] += MOD;
				add = -1;
			} else {
				add = 0;
			}
		});

		return this.trim();
	},
	mul: function(n){
		if(n.isZero() || !n) return this;

		var zero = UBigInteger(0);
		var arr = this.T.slice(0);
		var arg = { };
		var pos = 0;
		n.each(function(V, I, A){
			var ARR = arr.slice(0);
			ARR.forEach(function(v, i, A){
				A[i] = climb(arg, v, V, function(a, b, add){
					return (a) * (b) + (add || 0);
				});
			});
			if(arg.add) ARR.push(arg.add);
			zero._ADD(ARR, pos++);
			arg.add = 0;

		});
		zero.trim();
		return zero;
	},
	toString: function(){
		return this.isZero() ? '0' : this.T.slice(0).reverse().join(',');
	}
}

var a = 2;

var A = UBigInteger(2);
var B = UBigInteger(2);
for(var i = 0; i < 2048; i++){
	A = A.mul(B);
}

console.log(A)
console.log(A.toString())


function UBigIntegerNumber(n, a){
	if(n < MOD){
		a.push(n);
	} else {
		a.push(n % MOD);
		UBigIntegerNumber((n / MOD) << 0, a);
	}
}

function UBigInteger(n, r, a){

	if(n < 0) throw 'should be unsigned integer';

	var v;
	if(window === this){
		v = {};
		for(var p in UBigIntegerMethods){
			v[p] = UBigIntegerMethods[p];
		}
	} else {
		v = this;
	}
	v.T = [];
	if(n !== 0){
		if(!n || isNaN(n)) n = 0;
		if(typeof(n) == 'number'){
			UBigIntegerNumber(n, v.T);
		}
	}
	
	return v;
};
UBigInteger.prototype = UBigIntegerMethods



</script>

</body>
</html>